﻿using Sustainalytics.Accounts.BusinessLogic;
using Sustainalytics.Accounts.Service.Models;
using Sustainalytics.AuthOperations;
using Sustainalytics.DataLayer.Exceptions.AccountsAndUsers;
using Sustainalytics.Entities;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace Sustainalytics.Accounts.Service.Controllers
{

    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/accounts")]
    [LogControllerFilter(true, true, true)]
    public class AccountsController : ApiController
    {
        private readonly IAccountsManagement _accountsManagement;
        private readonly AccountWithIpManager _manager;

        public AccountsController(IAccountsManagement accountsManagement, IAuthOperations authOperations, AccountWithIpManager manager)
        {
            _accountsManagement = accountsManagement;
            _manager = manager;
        }

        [Route("")]
        public HttpResponseMessage Get([FromUri]ListOptions filters, bool tier1_or_tier2 = false, string status = null, string name = null, bool returnLastCrmSyncDate = false)
        {
            try
            {
                Entities.Status statusEnum;
                var nullableStatus = Enum.TryParse(status, out statusEnum) ? statusEnum : (Entities.Status?)null;

                if (filters != null && filters.GetCount)
                {
                    int accountsCount = 0;
                    try
                    {
                        accountsCount = _accountsManagement.GetAccountsTotalCount(nullableStatus, name, tier1_or_tier2);
                    }
                    catch (Exception)
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest, new { Code = ErrorCodes.ErrorRetrievingAccounts });
                    }

                    return Request.CreateResponse(HttpStatusCode.OK, accountsCount);
                }

                if (returnLastCrmSyncDate)
                {
                    string stringValue = "";
                    try
                    {
                        var lastCrymSyncDate = _accountsManagement.GetLastSyncDate(SyncType.Account);
                        stringValue = lastCrymSyncDate.HasValue ? lastCrymSyncDate.Value.ToString(System.Globalization.CultureInfo.InvariantCulture) : "";
                    }
                    catch (Exception ex)
                    {
                        return Request.CreateResponse(HttpStatusCode.BadRequest, new { Code = ErrorCodes.ErrorRetrievingAccounts });
                    }

                    return Request.CreateResponse(HttpStatusCode.OK, stringValue);
                }

                var response = _accountsManagement.GetAccounts(nullableStatus, name, filters, tier1_or_tier2);
                var accountsDto = new List<object>();
                response.ForEach(acc => accountsDto.Add(AccountDto.CreateWithNameIdTypeManagerStatus(acc)));

                return Request.CreateResponse(HttpStatusCode.OK, accountsDto);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound, new { Code = ErrorCodes.ErrorRetrievingAccounts });
            }
        }

        [Route("{accountId}")]
        public HttpResponseMessage Get(Guid accountId)
        {
            try
            {
                var response = _accountsManagement.GetAccountById(accountId);
                return Request.CreateResponse(HttpStatusCode.OK, AccountDto.CreateComplete(response));
            }
            catch (AccountNotFoundException ex)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound, new { Code = ErrorCodes.ErrorRetrievingSelectedAccount });
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ErrorCodes.ErrorRetrievingSelectedAccount });
            }
        }

        [HttpPost]
        [Route("ipauthentication")]
        public HttpResponseMessage Post(AccountIpAuthenticationDto auth)
        {
            try
            {
                return Request.CreateResponse(HttpStatusCode.Accepted,
                    _manager.CreateOrUpdate(new AccountIpAuthentication()
                    {
                        Id = auth.Id,
                        IpDatas = auth.IpDatas
                    }));
            }
            catch (AccountNotFoundException ex)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound,
                    new { Code = ErrorCodes.ErrorRetrievingSelectedAccount });
            }
            catch (AccountIpAuthenticationInvalidException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new
                {
                    Code = ErrorCodes.ErrorEditIpAuthenticationData
                });
            }
            catch (IpAccountOverlapingException ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new
                {
                    Code = ErrorCodes.ErrorEditIpAuthenticationDataIpOverlapping
                });
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ErrorCodes.Generic });
            }
        }

        [Route("ipauthentication/{accountid}")]
        public HttpResponseMessage GetIpAuthentication([FromUri] Guid? accountId)
        {
            try
            {
                var listData = _manager.GetAccounts(accountId);
                if (accountId.GetValueOrDefault() == Guid.Empty)
                {
                    return Request.CreateResponse(HttpStatusCode.Accepted, listData.Select(a => new AccountIpAuthenticationDto()
                    {
                        AccountName = a.AccountName,
                        Id = a.Id,
                        IpDatas = a.IpDatas
                    }));
                }
                var data = listData.FirstOrDefault();
                if (data == null) return Request.CreateResponse(HttpStatusCode.Accepted);
                return Request.CreateResponse(HttpStatusCode.Accepted, new AccountIpAuthenticationDto() { AccountName = data.AccountName, Id = data.Id, IpDatas = data.IpDatas ?? new List<IpData>() });
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError, new { Code = ErrorCodes.Generic });
            }
        }
    }
}
